package com.superWindCloud.learn_java;


import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;

public final class RingCache<T> {
    private final ArrayList<T> buffer;

    private int writeIndex;
    private int readIndex;
    private boolean isFull;
    private final ReentrantLock lock = new ReentrantLock();


    public RingCache(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException("Capacity must be positive");
        this.buffer = new ArrayList<>(capacity);
        for (int i = 0; i < capacity; i++) {
            buffer.add(i, null);
        }
    }

    public void put(T value) {
        lock.lock();
        try {
            buffer.set(writeIndex, value);
            writeIndex = (writeIndex + 1) % buffer.size();
            if (isFull) {
                readIndex = (readIndex + 1) % buffer.size();
            }

            if (writeIndex == readIndex) {
                isFull = true;
            }

        } finally {
            lock.unlock();
        }
    }

    public T get() {
        lock.lock();
        try {
            if (isEmptyDanger()) {
                return null;
            }
            var result = buffer.get(readIndex);
            buffer.set(readIndex, null);
            readIndex = (readIndex + 1) % buffer.size();
            isFull = false;
            return result;
        } finally {
            lock.unlock();
        }
    }

    public ArrayList<T> getBuffer() {
        return buffer;
    }

    public int getWriteIndex() {
        return writeIndex;
    }

    //@Contract注解主要用于描述方法的行为，包括方法的纯度（是否为纯函数）以及方法可能会修改的参数或状态。
    public int getReadIndex() {
        return readIndex;
    }

    public boolean isFull() {
        lock.lock();
        try {
            return isFull;
        } finally {
            lock.unlock();
        }
    }

    public boolean isEmpty() {
        lock.lock();
        try {
            return !isFull && writeIndex == readIndex;
        } finally {
            lock.unlock();
        }
    }


    ///  返回为读取的元素个数
    public int size() {
        lock.lock();
        if (this.isFull()) {
            return this.capacity();
        } else if (this.getWriteIndex() >= this.getReadIndex()) {
            return this.getWriteIndex() - this.getReadIndex();
        } else {
            return this.capacity() - (this.getReadIndex() - this.getWriteIndex());
        }
    }

    public int capacity() {
        return this.buffer.size();
    }

    private boolean isEmptyDanger() {
        return !isFull && this.writeIndex == this.readIndex;
    }

}
